#encoding:utf-8
'''
Created on 5 avr. 2011

@author: paraita

    Serveur de calcul: question 1.5.4

'''

import socket
import os

def serveur(p=8080):
    '''
        serveur au sens serveur de calcul
        il retourne le resultat du calcul au client
        sur le port p+1
        @param p le port sur lequel va ecouter le serveur de calcul
    '''
    sockin = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    sockout = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    
    rfd,wfd = os.pipe()
    
    pid = os.fork()
    
    if pid:
        os.close(rfd)
        port = p
        sockin.bind(("", port))
        
        print "Serveur en écoute sur", sockin.getsockname()[0],":",sockin.getsockname()[1]
        
        BUFSIZE = 1 << 20
        
        while True:
            datagrm, addr = sockin.recvfrom(BUFSIZE)
            print "serveur de calcul: requete de", sockin.getsockname()[0],":",sockin.getsockname()[1]
            
            a1,op1,b1 = datagrm.rstrip(' ').rpartition('+')
            a2,op2,b2 = datagrm.rstrip(' ').rpartition('-')
            a3,op3,b3 = datagrm.rstrip(' ').rpartition('/')
            a4,op4,b4 = datagrm.rstrip(' ').rpartition('*')
            
            if op1 == '+':
                print "calcul coté serveur:",int(a1),"+",int(b1)
                resultat = int(a1) + int(b1)
                toThePipe = "" + addr[0] + "X" + str(resultat)
                os.write(wfd, toThePipe)
            if op2 == '-':
                print "calcul coté serveur:",int(a2),"-",int(b2)
                resultat = int(a2) - int(b2)
                toThePipe = addr[0] + "X" + str(resultat)
                os.write(wfd, toThePipe)
            if op3 == '/':
                print "calcul coté serveur:",int(a3),"/",int(b3)
                resultat = int(a3) / int(b3)
                toThePipe = addr[0] + "X" + str(resultat)
                os.write(wfd, toThePipe)
            if op4 == '*':
                print "calcul coté serveur:"+a4+"*"+b4
                resultat = int(a4) * int(b4)
                toThePipe = addr[0] + "X" + str(resultat)
                os.write(wfd, toThePipe)
                
    else:
        os.close(wfd)
        while True:
            reponse = os.read(rfd, 512)
            if reponse:
                addr,resultatCalcul = reponse.split('X')
                sockout.sendto(resultatCalcul, (addr, p+1))
            

def client(dest="127.0.0.1", p=8080):
    '''
        le client va demander au serveur de faire un calcul
        il ecoute et attend le resultat sur le port p+1
        @param dest l'adresse ip du serveur de calcul
        @param p le port de communication (d'envoi)
    '''
    sockin = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    sockout = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    
    port_dest = p
    ip_dest = dest
    
    
    
    pid = os.fork()
    
    if pid:
        msg = ""
        while msg <> "exit":
            msg = raw_input("~")
            try:
                sockout.sendto(msg, (ip_dest, port_dest))
            except socket.error:
                print "erreur de connexion !!!"
                break
    else:
        sockin.bind(("", port_dest+1))
        BUFSIZE = 1 << 20
        while True:
            datagrm, addr = sockin.recvfrom(BUFSIZE)
            print "reponse du serveur de calcul:\n",datagrm
            
        
def surMachineLocale(port):
    '''
        pour le test sur une machine unique
        dans ce cas on fork et chacun des processus va s'occuper d'un role
    '''
    pid = os.fork()
    if pid:
        serveur(p=port)
    else:
        client(dest="127.0.0.1",p=port)


if __name__ == '__main__':
    
    PORT = 8080
    #client(dest="192.168.0.13",p=PORT)
    surMachineLocale(port=PORT)

    